package tp.pr5.mv.window;

import java.awt.BorderLayout;
import java.awt.Font;

import javax.swing.BorderFactory;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

import tp.pr5.mv.CPU;
import tp.pr5.mv.Instruction;
import tp.pr5.mv.Memory;
import tp.pr5.mv.OperandStack;
import tp.pr5.mv.ProgramCounter;
import tp.pr5.mv.ProgramMV;

@SuppressWarnings("serial")
public class ProgramPanel extends javax.swing.JPanel implements CPU.Observer {
	
	/* El program panel se componde de un JTextArea que incluiremos en un JScrollPane para que así
	 * tenga barra de desplazamiento vertical y horizontal
	 * */
	private JTextArea textProgram;
	private ProgramMV program;
	
	
	
	public ProgramPanel() {
		
		super();
		setBorder(BorderFactory.createTitledBorder("Programa") );
		initialize();
	}
	
	public void initialize() {
		
	
		textProgram = new JTextArea();
		textProgram.setFont(new Font("Courier New", Font.PLAIN, 12) );
		textProgram.setEditable(false);	
	    textProgram.setColumns(20);
	    setLayout(new BorderLayout());
		
		add( new JScrollPane( textProgram ));
		
		program = new ProgramMV();
	}
	
	public void repaintProgram( int pc ) { // Metodo que repinta el asterisco que marca la instrucción a ejecutar
		
		textProgram.setText("");   // Puesta en blanco del texto.
		
		for ( int i = 0; i < program.getNumInstrs(); i++ )
		{
			if ( i == pc ) 
			{
				textProgram.append("*");
				textProgram.append( String.format( "%3d", i ) + ":  " + program.getInstrAt(i).toString() + "\n" );
			}
			else
				textProgram.append( String.format( "%4d", i ) + ":  " + program.getInstrAt(i).toString() + "\n" );
		}
		
		
	}

	@Override
	public void onStartInstrExecution(Instruction ins) {}

	@Override
	public void onEndInstrExecution(Instruction instr, Memory mem,
			OperandStack stack, final ProgramCounter pc) { // Cuando se acaba la ejecución de una instruccion se repinta el JTextArea
		
		SwingUtilities.invokeLater(
				new Runnable() {
				 		public void run() {
				 			repaintProgram(pc.getPC());
				 		}
				}
		);
	}

	@Override
	public void onHalt() {}

	@Override
	public void onReset(ProgramMV program) { // Cuando se inserta un programa nuevo se repinta el JTextArea
		
	
		this.program = program;
	
		SwingUtilities.invokeLater(
				new Runnable() {
				 		public void run() {
				 			repaintProgram(0); // El pc estará valdrá 0
				 		}
				}
		);
	}

	@Override
	public void onStartRun() {}

	@Override
	public void onEndRun(boolean aborted){}		

	@Override
	public void onTrap(Instruction instr, String trapMessage){}
	
	
	
}


